package com.collection.web.shiro;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.dubbo.config.annotation.Reference;
import com.collection.api.entity.sys.SysResource;
import com.collection.api.entity.sys.SysUser;
import com.collection.api.sys.ShiroService;
import com.collection.api.sys.SysUserService;
import com.collection.util.ReflectionUtils;
import com.collection.web.shiro.util.TreeNodeUtil;

/**
 * MyShiroRealm
 *  shiro的核心类  获取用户数据封装成subject  包含用户认证数据的封装 +用户鉴权所需 权限数据的封装
 */
public class MyShiroRealm extends AuthorizingRealm {

    private static final Logger logger = LoggerFactory.getLogger(MyShiroRealm.class);

    private List<String> defaultPermission = new ArrayList<String>();
   
	@Reference(version ="1.0.0")
	private SysUserService sysUserService;
	 
	@Reference(version ="1.0.0")
	private ShiroService shiroService; 
	
	
	/**
	 * 设置默认permission
	 * 
	 * @param defaultPermissionString
	 *            permission 如果存在多个值，使用逗号","分割
	 */
	public void setDefaultPermissionString(String defaultPermissionString) {
		String[] perms = StringUtils.split(defaultPermissionString, ",");
		CollectionUtils.addAll(defaultPermission, perms);
	}

	/**
	 * 设置默认permission
	 * 
	 * @param defaultPermission
	 *            permission
	 */
	public void setDefaultPermission(List<String> defaultPermission) {
		this.defaultPermission = defaultPermission;
	}

	
	
	/**
	 * 从数据库中加载用户的权限  包含用户角色权限 用户模块权限 以及用户分组权限
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection priCollenction) {
		
		logger.info("权限认证方法：MyShiroRealm.doGetAuthorizationInfo()");
		SimpleAuthorizationInfo info =  new SimpleAuthorizationInfo();
		ShiroUser model = priCollenction.oneByType(ShiroUser.class);
		logger.info( "找不到principals中的ShiroUser");
		List<SysResource> resources = null; //adminShiroBiz.findResourceByRoleId(NumberUtils.toInt(model.getSysUser().getRoleId()));
		
		logger.info("resources："+resources.size());
		List<String> permissions = getPermsValue(resources);
		
		 //添加默认的permissions到permissions
        if (CollectionUtils.isNotEmpty(defaultPermission)) {
        	CollectionUtils.addAll(permissions, defaultPermission.iterator());
        }
        
		// 添加用户拥有的permission
		info.addStringPermissions(permissions);
		// 添加用户拥有的role
		// info.addRoles(rolesList);

		model.setMenus(TreeNodeUtil.getfatherNode(resources));
		// model.setAuthorizationInfo(authorizationInfo)

		return info;
	}
	
	
	
	
	/**
	 * 用户认证操作
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken authenticationtoken) throws AuthenticationException {
		 
        logger.info("身份认证方法封装数据开始：MyShiroRealm.doGetAuthenticationInfo()");
		
		UsernamePasswordToken token = (UsernamePasswordToken) authenticationtoken;
		String userName = token.getUsername();
  
		SysUser user =  sysUserService.findByUsername(userName);
		if (user == null) {
			throw new UnknownAccountException("用户名或密码不正确");// 没找到帐号
		}

		if (Boolean.TRUE.equals(user.getLocked())) {
			throw new LockedAccountException("账号已锁定"); // 帐号锁定
		}
		if(StringUtils.isBlank(String.valueOf(token.getPassword()))){
			throw new AccountException("用户名或密码不正确");// 没找到帐号
		}
		ShiroUser shiroUser = new ShiroUser(user);
		if(user !=null ){
			List<SysResource> resources =   shiroService.findResourceByRoleId( Integer.parseInt(user.getRoleId()) );
			
			logger.info("resources："+resources.size());
			List<String> permissions = getPermsValue(resources);
			
			 //添加默认的permissions到permissions
	        if (CollectionUtils.isNotEmpty(defaultPermission)) {
	        	CollectionUtils.addAll(permissions, defaultPermission.iterator());
	        }
	        
			// 添加用户拥有的role
			// info.addRoles(rolesList);

			shiroUser.setMenus(TreeNodeUtil.getfatherNode(resources));
		}
		
		return new SimpleAuthenticationInfo(shiroUser,user.getPassword(),getName());
	}
	
	/*
	 * 清楚缓存中  当前用户的权限信息
	 * 
	 */
	public void clearCachedAuthorizationInfo() {
		PrincipalCollection principalCollection = SecurityUtils.getSubject()
				.getPrincipals();
		SimplePrincipalCollection principals = new SimplePrincipalCollection(
				principalCollection, getName());
		super.clearCachedAuthorizationInfo(principals);
	}
	
	
	
	/**
	 * 清楚PrincipalCollection的用户数据
	 */
	public void clearCachedAuthorizationInfo(
			PrincipalCollection principalCollection) {
		SimplePrincipalCollection principals = new SimplePrincipalCollection(
				principalCollection, getName());
		super.clearCachedAuthorizationInfo(principals);
	}
	
	
	public static void main(String[] args) {
		
		String url="/user/add";
		String[] split = url.split("/");
		//for (String string : split) {
			System.out.println(split[1]);
		//}
		
		
	}
	
	public List<Menu> extractMenusFromResources(List<SysResource> list) {
		List<Menu> menus = new ArrayList<Menu>();
		Map<Integer,List<Menu>> tempMap= new HashMap<Integer,List<Menu>>();
		Menu menu =null;
		List<Menu> childList =null;
		for(SysResource resource:list){
				menu =new Menu(resource.getId(),resource.getName(),StringUtils.replace(resource.getUrl(), "**", ""),resource.getSort(),null);
				if(resource.getParentId()==0){
					menus.add(menu);
				}else{
					if(null==tempMap.get(resource.getParentId())){
						childList = new ArrayList<Menu>();
						 childList.add(menu);
						tempMap.put(resource.getParentId(), childList);
					}else{
						tempMap.get(resource.getParentId()).add(menu);
					}
				}
			 
		}
		for(Menu ms :menus){
			if(tempMap.get(ms.getId())!=null){
				ms.setChildren(tempMap.get(ms.getId()));
			}
		}
		return menus;
	}
	
	
	private List<String> getPermsValue(List<SysResource> collection){
		 List<String> result = new ArrayList<String>();
		try {
			for (SysResource obj : collection) {
				if(StringUtils.isNotBlank(obj.getPermission())){
					result.add(getValueForPattern(obj.getPermission()));
				}
			}
		} catch (Exception e) {
			throw ReflectionUtils.convertReflectionExceptionToUnchecked(e);
		}
		return result;
	}

	/**
	 * 通过正则表达式获取字符串集合的值
	 * 
	 * @param obj 字符串集合
	 * @param regex 表达式
	 * 
	 * @return List
	 */
	private String getValueForPattern(String str){
		String res=null;
		Pattern pattern = Pattern.compile("perms\\[(.*?)\\]");
       Matcher matcher = pattern.matcher(str);
       while(matcher.find()){
       	res=matcher.group(1);
       }
       
		return res;
	}
	
}

